package vip.ola.code.ctrl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import vip.ola.code.common.ctrl.BaseController;
import vip.ola.code.common.service.RpcCommonService;
import vip.ola.code.secruity.JwtUser;
import vip.ola.core.common.annotation.MethodLog;
import vip.ola.core.common.constant.Constant;
import vip.ola.core.common.constant.RetEnum;
import vip.ola.core.common.domain.BizResponse;
import vip.ola.core.common.domain.MenuTreeBuilder;
import vip.ola.core.common.domain.PayResponse;
import vip.ola.core.common.util.MyLog;
import vip.ola.core.common.util.StrUtil;
import vip.ola.core.entity.SysResource;
import vip.ola.core.entity.code.CodeOrder;
import vip.ola.core.entity.code.CodeUser;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;

import static vip.ola.core.common.constant.CodeConstant.*;
import static vip.ola.core.common.constant.Constant.CODE_ROLE_NORMAL;
import static vip.ola.core.common.constant.Constant.SYSTEM_CODE;
import static vip.ola.core.common.constant.SysConfigConstant.CODE_CODE_BUS_RATE;
import static vip.ola.core.common.constant.SysConfigConstant.TYPE_CODE;

@RestController
@RequestMapping(Constant.CODE_CONTROLLER_ROOT_PATH)
@PreAuthorize("hasRole('" + CODE_ROLE_NORMAL + "')")
public class CodeController extends BaseController {

    private final static MyLog _log = MyLog.getLog(CodeController.class);

    @Autowired
    private RpcCommonService rpcService;

    /**
     * 查询商户信息
     *
     * @return
     */
    @RequestMapping("/get")
    public ResponseEntity<?> get() {
        return ResponseEntity.ok(PayResponse.buildSuccess(getUser()));
    }

    @RequestMapping("/current")
    public ResponseEntity<?> current() {
        CodeUser codeUser = rpcService.codeUserService.getById(getUser().getId());
        codeUser.setPassword(null);
        codeUser.setGoogleAuthSecret(null);
        return ResponseEntity.ok(PayResponse.buildSuccess(codeUser));
    }

    @RequestMapping("/getConfig")
    public ResponseEntity<?> getConfig() {
        JSONObject json = rpcService.rpcSysConfigService.getSysConfigObj(TYPE_CODE);
        return ResponseEntity.ok(PayResponse.buildSuccess(json));
    }

    /**
     * 查询商户菜单
     *
     * @return
     */
    @RequestMapping("/menu")
    public ResponseEntity<?> getMenu() {
        Integer mchType = getUser().getType();
        List<SysResource> sysResourceList = rpcService.rpcSysService.selectAllResource(SYSTEM_CODE);
        List<MenuTreeBuilder.Node> nodeList = new LinkedList<>();
        for (SysResource sysResource : sysResourceList) {
            // 判断是否显示该菜单,平台账户和私有账户显示的菜单可能不同
            // 用资源表中的property区分,该值为空都可见.否则对应商户类型,如1 表示平台账户可见, 1,2 表示平台账户和私有账户都可见
            boolean isShow = true;
            String property = sysResource.getProperty();
            if (StringUtils.isNotBlank(property)) {
                isShow = false;
                String[] propertys = property.split(",");
                for (String str : propertys) {
                    if (str.equalsIgnoreCase(mchType.toString())) {
                        isShow = true;
                        break;
                    }
                }
            }
            if (!isShow) continue;
            MenuTreeBuilder.Node node = new MenuTreeBuilder.Node();
            node.setResourceId(sysResource.getResourceId());
            node.setName(sysResource.getName());
            node.setTitle(sysResource.getTitle());
            if (StringUtils.isNotBlank(sysResource.getJump())) node.setJump(sysResource.getJump());
            if (StringUtils.isNotBlank(sysResource.getIcon())) node.setIcon(sysResource.getIcon());
            node.setParentId(sysResource.getParentId());
            nodeList.add(node);
        }
        return ResponseEntity.ok(PayResponse.buildSuccess(JSONArray.parseArray(MenuTreeBuilder.buildTree(nodeList))));
    }

    /**
     * 账户数据
     *
     * @return
     */
    @RequestMapping("/count4Account")
    public ResponseEntity<?> count4Account() {
        CodeUser codeUser;
        if (CODE_CODE_SUB_TYPE.equals(getUser().getType())) {
            codeUser = rpcService.codeUserService.getById(getUser().getCodeBusId());
        } else {
            codeUser = rpcService.codeUserService.getById(getUser().getId());
        }
        return ResponseEntity.ok(PayResponse.buildSuccess(codeUser));
    }

    /**
     * 统计收入数据
     *
     * @return
     */
    @RequestMapping("/count4dayIncome")
    public ResponseEntity<?> count4DayIncome() {
        JwtUser user = getUser();
        CodeOrder codeOrder = new CodeOrder();
        if (CODE_CODE_TYPE.equals(user.getType()) || CODE_CODE_SUB_TYPE.equals(user.getType())) {
            codeOrder.setCodeBusId(user.getCodeBusId());
        } else if (CODE_AGENT_TYPE.equals(user.getType())) {
            codeOrder.setAgentId(user.getAgentId());
        } else if (CODE_USER_TYPE.equals(user.getType())) {
            codeOrder.setUserId(user.getId());
        }

        // 今日
        LocalDateTime startTime = LocalDateTime.now().withHour(0).withMinute(0).withSecond(0);
        LocalDateTime endTime = LocalDateTime.now().withHour(23).withMinute(59).withSecond(59);
        codeOrder.setCreateTime(startTime);
        codeOrder.setUpdateTime(endTime);
        Map<String, Object> todayPayData = rpcService.codeOrderService.countSuccess(codeOrder);
        if (todayPayData == null) {
            todayPayData = new HashMap<>();
            todayPayData.put("totalCount", 0);
            todayPayData.put("totalAmount", 0);
            todayPayData.put("totalProfit", 0);
        } else {
            BigDecimal totalCodeBusProfit = new BigDecimal(Optional.ofNullable(todayPayData.get("totalCodeBusProfit")).map(Object::toString).orElse("0"));
            BigDecimal totalAgentProfit = new BigDecimal(Optional.ofNullable(todayPayData.get("totalAgentProfit")).map(Object::toString).orElse("0"));
            BigDecimal totalUserProfit = new BigDecimal(Optional.ofNullable(todayPayData.get("totalUserProfit")).map(Object::toString).orElse("0"));
            if (CODE_CODE_TYPE.equals(user.getType()) || CODE_CODE_SUB_TYPE.equals(user.getType())) {
                todayPayData.put("totalProfit", totalCodeBusProfit.add(totalAgentProfit).add(totalUserProfit));
            } else if (CODE_AGENT_TYPE.equals(user.getType())) {
                todayPayData.put("totalProfit", totalAgentProfit.add(totalUserProfit));
            } else if (CODE_USER_TYPE.equals(user.getType())) {
                todayPayData.put("totalProfit", totalUserProfit);
            }
            todayPayData.put("totalAmount", todayPayData.getOrDefault("totalAmount", 0));
        }
        // 昨日
        codeOrder.setCreateTime(startTime.minusDays(1));
        codeOrder.setUpdateTime(endTime.minusDays(1));
        Map yesterdayPayData = rpcService.codeOrderService.countSuccess(codeOrder);
        if (yesterdayPayData == null) {
            yesterdayPayData = new HashMap<>();
            yesterdayPayData.put("totalCount", 0);
            yesterdayPayData.put("totalAmount", 0);
            yesterdayPayData.put("totalProfit", 0);
        } else {
            BigDecimal totalCodeBusProfit = new BigDecimal(Optional.ofNullable(yesterdayPayData.get("totalCodeBusProfit")).map(Object::toString).orElse("0"));
            BigDecimal totalAgentProfit = new BigDecimal(Optional.ofNullable(yesterdayPayData.get("totalAgentProfit")).map(Object::toString).orElse("0"));
            BigDecimal totalUserProfit = new BigDecimal(Optional.ofNullable(yesterdayPayData.get("totalUserProfit")).map(Object::toString).orElse("0"));
            if (CODE_CODE_TYPE.equals(user.getType()) || CODE_CODE_SUB_TYPE.equals(user.getType())) {
                yesterdayPayData.put("totalProfit", totalCodeBusProfit.add(totalAgentProfit).add(totalUserProfit));
            } else if (CODE_AGENT_TYPE.equals(user.getType())) {
                yesterdayPayData.put("totalProfit", totalAgentProfit.add(totalUserProfit));
            } else if (CODE_USER_TYPE.equals(user.getType())) {
                yesterdayPayData.put("totalProfit", totalUserProfit);
            }
            yesterdayPayData.put("totalAmount", yesterdayPayData.getOrDefault("totalAmount", 0));
        }
        JSONObject object = new JSONObject();
        object.put("todayPayData", todayPayData);
        object.put("yesterdayPayData", yesterdayPayData);
        return ResponseEntity.ok(PayResponse.buildSuccess(object));
    }

    /**
     * 修改登录密码
     *
     * @return
     */
    @RequestMapping("/pwd_update")
    @MethodLog(remark = "修改登录密码")
    public ResponseEntity<?> updatePassword(HttpServletRequest request) {
        // 旧密码
        String oldRawPassword = getStringRequired("oldPassword");
        // 新密码
        String rawPassword = getStringRequired("password");
        // 验证旧密码是否正确
        CodeUser codeUser = rpcService.codeUserService.getById(getUser().getId());
        BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
        if (!encoder.matches(oldRawPassword, codeUser.getPassword())) {
            return ResponseEntity.ok(BizResponse.build(RetEnum.RET_MCH_OLDPASSWORD_NOT_MATCH));
        }
        // 判断新密码格式
        if (!StrUtil.checkPassword(rawPassword)) {
            return ResponseEntity.ok(BizResponse.build(RetEnum.RET_MCH_PASSWORD_FORMAT_FAIL));
        }
        codeUser = new CodeUser();
        codeUser.setId(getUser().getId());
        codeUser.setPassword(encoder.encode(rawPassword));
        codeUser.setLastPasswordResetTime(LocalDateTime.now());
        boolean isSuc = rpcService.codeUserService.updateById(codeUser);
        if (isSuc) {
            ResponseEntity.ok(PayResponse.build(RetEnum.RET_COMM_OPERATION_FAIL));
        }
        return ResponseEntity.ok(PayResponse.buildSuccess());
    }

}